#include "audiosink.h"

#include "modules/pulse.h"
#include "modules/tcpdevice.h"
#include "modules/udpdevice.h"
#include "modules/nativeaudio.h"
#include "modules/phonondevice.h"
#include "modules/alsadevice.h"

#include <QIODevice>
#include <QDebug>

AudioSink::AudioSink(const QString sinkName,AudioSink::userConfig userConfig, QObject *parent) :
    QObject(parent)
{
    devOut = 0;

    currentMode = userConfig.outputMode;
    this->format = userConfig.format;
    say("creating sink for " + sinkName);

    if (currentMode == AudioSink::Mute) return;
#ifdef PULSE
    else if (currentMode == AudioSink::PulseAudio) devOut = new PulseDevice(userConfig.sinkName,NULL,format,this);
#endif
#ifdef PHONON
    else if (currentMode == AudioSink::Phonon) devOut = new PhononDevice(this);
#endif
#ifdef ALSA
    else if (currentMode == AudioSink::Alsa) devOut = new AlsaDevice(format,this);
#endif
#ifdef MULTIMEDIA
    else if (currentMode == AudioSink::Native) devOut = new NativeAudio(sinkName,format,this);
#endif
    else if (currentMode == AudioSink::Tcp) devOut = new TcpDevice(userConfig.tcpConfig.host,userConfig.tcpConfig.port,format,this);
    else if (currentMode == AudioSink::Udp) devOut = new UdpDevice(userConfig.tcpConfig.host,userConfig.tcpConfig.port,format,this);
    if (!devOut) {
        say("no output module: this user will be muted");
        return;
    }

    say("trying to open the output device...");
    if (!devOut->open(QIODevice::WriteOnly)) {
        say("unable to open output device.");
        devOut->deleteLater();
        devOut = 0;
    }
    else say("device opened succesfully");
}
void AudioSink::sinkStream(QByteArray *sinkStream) {
    if (devOut) devOut->write(*sinkStream);
}

AudioSink::~AudioSink() {
     devOut->deleteLater();
}
void AudioSink::setFormat(AudioFormat newFormat) {
     *this->format = newFormat;
}
void AudioSink::setTargetDevice(QIODevice *targetDevice) {
    /* Example of use:
        QFile *file = new QFile("mytestfile.wav");
        file->open(QIODevice::WriteOnly);
        QIODevice *devOut = file;
        QAudioSink *sink = new QAudioSink("test",QAudioSink::Device,this);
        sink->setTargetDevice(devOut);
        //and now you are ready to use sink->sinkStream()
    */
    devOut = targetDevice;
}
bool AudioSink::isReady() {
    if (!devOut) return false;
    else return true;
}

void AudioSink::say(QString message) {
    qDebug() << "AudioSink: " + message;
}
QIODevice* AudioSink::getDevice() {
    return devOut;
}

AudioSink::Mode AudioSink::getModeFromString(QString modeName) {
    modeName = modeName.toLower();
    if (modeName.isEmpty()) return AudioSink::Speakers;
    else if (modeName == "native") return AudioSink::Native;
#ifdef PULSE
    else if (modeName == "pulse") return AudioSink::PulseAudio;
#endif
    else if (modeName == "relay") return AudioSink::Tcp;
    else if (modeName == "udp") return AudioSink::Udp;
#ifdef PHONON
    else if (modeName == "phonon") return AudioSink::Phonon;
#endif
#ifdef ALSA
    else if (modeName == "alsa") return AudioSink::Alsa;
#endif
    return AudioSink::getDefaultModule();
}
AudioSink::Mode AudioSink::getDefaultModule() {
#ifdef PULSE
    return AudioSink::PulseAudio;
#endif
#ifdef MULTIMEDIA
    return AudioSink::Native;
#endif
#ifdef PHONON
    return AudioSink::Phonon;
#endif
    //if no module is available: using the mute device
    return AudioSink::Mute;
}
